package com.business.dynamic.controller;


import com.alibaba.fastjson.JSONObject;
import com.business.common.dto.R;
import com.business.common.enums.BusinessExceptionEnum;
import com.business.common.enums.ErrorEnum;
import com.business.common.exception.CustomException;
import com.business.common.utils.SystemClock;
import com.business.dynamic.entity.DynamicLike;
import com.business.dynamic.entity.vo.DynamicLikeVo;
import com.business.dynamic.service.DynamicLikeService;
import com.business.dynamic.service.impl.UserServiceImpl;
import com.business.redis.ExpiresTimeEnum;
import com.business.redis.RedisLock;
import com.business.redis.constant.RedisKeyConstant;
import com.business.redis.utils.RedisKeysUtil;
import com.business.redis.utils.RedisUtil;
import com.business.user.annotation.FrequentRequest;
import com.business.user.annotation.TokenPermission;
import com.business.user.entity.UserDetailsDto;
import com.business.user.entity.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 用户喜欢表: 后端controller类
 *
 * @author chenjiehong
 * @date 2019-11-29 15:15:38
 * @since 1.0
 */
@RestController
@RequestMapping(value = "/like")
public class DynamicLikeController {


    @Autowired
    private DynamicLikeService dynamicLikeServiceImpl;

    @Autowired
    private UserServiceImpl userService;

    private ThreadPoolExecutor pool = new ThreadPoolExecutor(9, 30, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    private void asynAddRedis(String key, Integer dynamicId) {
        //异步添加到缓存
        pool.execute(() -> {
            List<DynamicLike> list = dynamicLikeServiceImpl.queryList(dynamicId);
            RedisLock redisLock = RedisLock.build(key);
            try {
                redisLock.lock();
                for (DynamicLike dynamicLike : list) {
                    //插入缓存
                    RedisUtil.addZSetValue(key, dynamicLike.getUserId(), dynamicLike.getCreateTime().getTime());
                }
                RedisUtil.expire(key, ExpiresTimeEnum.LEVEL_24.getExpiresTime());
            } finally {
                redisLock.unlock();
            }
        });
    }

    /**
     * 新增用户喜欢表
     *
     * @param params
     * @date 2019-11-29 15:15:38
     */
    @PostMapping("/add")
    @ResponseBody
    @TokenPermission
    @FrequentRequest(15)//控制频繁操作 一分钟内可以操作15次
    public R add(@RequestBody JSONObject params, UserDto userDto) {
        Integer dynamicId = params.getInteger("dynamicId");
        if (dynamicId == null) {
            throw new CustomException(ErrorEnum.PARAMS_LOSE, "dynamicId");
        }
        String key = String.format(RedisKeyConstant.DYNAMIC_LIKE, dynamicId);

        //如果缓存不存在 从数据库中读取
        if (!RedisUtil.hasKey(key)) {
            DynamicLike dynamicLike = new DynamicLike();
            dynamicLike.setDynamicId(dynamicId);
            dynamicLike.setUserId(userDto.getId());
            Integer r = dynamicLikeServiceImpl.addAndCheck(dynamicLike);
            //异步添加到缓存
            asynAddRedis(key, dynamicId);
            //插入缓存
            RedisUtil.addZSetValue(key, userDto.getId(), SystemClock.now());
            return R.success(r);
        }
        //从缓存中读取
        //先获取锁
        RedisLock redisLock = RedisLock.build(key);
        try {
            redisLock.lock();
            //添加喜欢
            boolean existFlag = RedisUtil.addZSetValue(key, userDto.getId(), SystemClock.now());
            if (existFlag) {
                //添加数据库
                DynamicLike dynamicLike = new DynamicLike();
                dynamicLike.setDynamicId(dynamicId);
                dynamicLike.setUserId(userDto.getId());
                dynamicLikeServiceImpl.addAndCheck(dynamicLike);
                //返回 总数
                return R.success(RedisUtil.getZSetSize(key));
            } else {
                //重复点赞
                return R.error(BusinessExceptionEnum.LIKE_EXIST, RedisUtil.getZSetSize(key));
            }
        } finally {
            redisLock.unlock();
        }

    }


    /**
     * 删除用户喜欢表
     *
     * @param params
     * @date 2019-11-29 15:15:38
     */
    @PostMapping("/delete")
    @ResponseBody
    @TokenPermission
    @FrequentRequest(15)//控制频繁操作 一分钟内可以操作15次
    public R delete(@RequestBody JSONObject params, UserDto userDto) {
        Integer dynamicId = params.getInteger("dynamicId");
        if (dynamicId == null) {
            throw new CustomException(ErrorEnum.PARAMS_LOSE, "dynamicId");
        }
        String key = String.format(RedisKeyConstant.DYNAMIC_LIKE, dynamicId);
        //如果缓存不存在 从数据库中读取
        if (!RedisUtil.hasKey(key)) {
            DynamicLike dynamicLike = new DynamicLike();
            dynamicLike.setDynamicId(dynamicId);
            dynamicLike.setUserId(userDto.getId());
            Integer r = dynamicLikeServiceImpl.delete(dynamicLike);
            //异步添加到缓存
            asynAddRedis(key, dynamicId);
            return R.success(r);
        }
        //从缓存中读取
        //先获取锁
        RedisLock redisLock = RedisLock.build(key);
        try {
            redisLock.lock();
            //删除喜欢
            long existFlag = RedisUtil.removeZSet(key, userDto.getId());
            if (existFlag > 0) {
                //添加数据库
                DynamicLike dynamicLike = new DynamicLike();
                dynamicLike.setDynamicId(dynamicId);
                dynamicLike.setUserId(userDto.getId());
                dynamicLikeServiceImpl.delete(dynamicLike);
            }
            //返回 总数
            return R.success(RedisUtil.getZSetSize(key));
        } finally {
            redisLock.unlock();
        }
    }


    /**
     * 获取用户点赞列表
     *
     * @param params
     * @date 2019-11-29 15:15:38
     */
    @PostMapping("/getUserList")
    @ResponseBody
    @TokenPermission(required = false)
    public R getUserList(@RequestBody JSONObject params, UserDto userDto) {
        Integer dynamicId = params.getInteger("dynamicId");
        if (dynamicId == null) {
            throw new CustomException(ErrorEnum.PARAMS_LOSE, "dynamicId");
        }
        String key = String.format(RedisKeyConstant.DYNAMIC_LIKE, dynamicId);
        Set<Integer> userIds = null;
        if (!RedisUtil.hasKey(key)) {
            List<DynamicLike> list = dynamicLikeServiceImpl.queryList(dynamicId);
            userIds = new HashSet<>();
            for (DynamicLike dynamicLike : list) {
                userIds.add(dynamicLike.getUserId());
                //插入缓存
                RedisUtil.addZSetValue(key, dynamicLike.getUserId(), dynamicLike.getCreateTime().getTime());
            }
            RedisUtil.expire(key, ExpiresTimeEnum.LEVEL_24.getExpiresTime());
        } else {
            //获取全部
            userIds = RedisUtil.getZSetValues(key, 0, Integer.SIZE);
        }
        List<DynamicLikeVo> likeUserList = new ArrayList<>();
        Integer myLiked = 0;//自己有没有点赞

        //获取用户信息
        Map<Integer, UserDetailsDto> nameMap = userService.getUserNameList(userIds);
        for (Integer userId : userIds) {
            UserDetailsDto u = nameMap.get(userId);
            //自己也点赞了
            if (userDto != null && userId.equals(userDto.getId())) {
                myLiked = 1;
            }
            if (u != null) {
                DynamicLikeVo dynamicLikeVo = new DynamicLikeVo();
                dynamicLikeVo.setUserId(userId);
                dynamicLikeVo.setDynamicId(dynamicId);
                dynamicLikeVo.setUserRealName(u.getRealName());
                dynamicLikeVo.setUserHeadUrl(u.getHeadUrl());
                likeUserList.add(dynamicLikeVo);
            }
        }
        HashMap<String, Object> resultMap = new HashMap<>();
        resultMap.put("likeUserList", likeUserList);
        resultMap.put("myLiked", myLiked);

        return R.success(resultMap);
    }


}